class Drop {
  constructor(container = null) {
    this.container = container;
    this.source = null;
    this.init();
  }

  init() {
    this.eventListener();
  }

  /**
   * @name getContainDropOver
   * @description 判断当前拖拽元素进入元素，其包含drop-over属性是当前元素还是祖先元素，找到并返回包含drop-over属性的元素，方便移除类样式
   * @param {HTMLElement} node
   * @returns {HTMLElement}
   */
  getContainDropOver(node) {
    while (node) {
      if (node.classList.contains("drop-over")) {
        break
      }
      node = node.parentNode;
    }
    return node
  }

  /**
   * @name isFromSource
   * @description 判断当前元素，其包含data-drop属性的最外层祖先元素是否为source区域
   * @param {HTMLElement} node
   * @returns {HTMLElement}
   */
  isFromSource(node) {
    return this.getOutermostNode(node).classList.contains("source");
  }

  /**
   * @name getOutermostNode
   * @description 拿到拖拽元素包含data-drop属性的最外层祖先元素
   * @param {HTMLElement} node
   * @returns {HTMLElement}
   */
  getOutermostNode(node) {
    while (node) {
      if (node.parentNode.dataset.drop) {
        node = node.parentNode;
      } else {
        break;
      }
    }
    return node;
  }

  clearDropOver() {
    const dropOverNodes = document.querySelectorAll(".drop-over");
    dropOverNodes.forEach((node) => {
      node.classList.remove("drop-over");
    })
  }

  eventListener() {
    this.container.addEventListener("dragstart", (e) => {
      // e.preventDefault();
      if (e.target.dataset.drop) {
        e.target.dataset.drop = "move";
        // 保存拖拽元素
        this.source = e.target;
        // console.log("start", e.target.dataset.drop);
        e.dataTransfer.effectAllowed = "move";
      }
    });
    this.container.addEventListener("dragover", (e) => {
      // 允许元素上面可以悬停元素
      e.preventDefault();
    });
    this.container.addEventListener("dragenter", (e) => {
      e.preventDefault();
      // console.log("enter", e.target);
      if (e.target.dataset.drop) {
        // 先移除所有含有drop-over类样式的元素的drop-over类样式
        this.clearDropOver()
        // 添加类样式
        // console.log("enterOutermostNode", this.getOutermostNode(e.target));
        this.getOutermostNode(e.target).classList.add("drop-over");
      }
    });
    this.container.addEventListener("dragleave", (e) => {
      e.preventDefault();
      // console.log("leave", e.target);
    });
    this.container.addEventListener("drop", (e) => {
      e.preventDefault();
      // console.log("drop", e.target.dataset.drop);
      // 清除类样式
      this.clearDropOver();
      // 判断是否为可放置区域
      if (!e.target.dataset.drop) {
        // （在未将拖拽元素插入到放置区域内之前，拖拽元素依旧还是处在原区域之内）
        this.source = null;
        return;
      }
      // 判断放置区域是否为source区域
      if (this.isFromSource(e.target)) {
        // 判断拖拽元素是否来自source区域,排除来自source区域的拖拽元素放置入source区域，导致source区域置空
        if (this.isFromSource(this.source)) {
          this.source = null;
          return;
        }
        // 置空拖拽元素原区域内的拖拽元素（在未将拖拽元素插入到放置区域内之前，拖拽元素依旧还是处在原区域之内）
        this.getOutermostNode(this.source).innerHTML = "";
        this.source = null;
        return;
      }
      // 判断该放置区域是否已经有拖拽元素了
      if (e.target.firstChild || this.source.tagName === e.target.tagName) {
        // （在未将拖拽元素插入到放置区域内之前，拖拽元素依旧还是处在原区域之内）
        this.source = null;
        return;
      }
      this.source.dataset.drop = e.target.dataset.drop;
      // 拖拽元素是否来自source区域
      if (!this.isFromSource(this.source)) {
        e.target.innerHTML = "";
        e.target.appendChild(this.source);
        return;
      }
      const clone = this.source.cloneNode(true);
      e.target.innerHTML = "";
      e.target.appendChild(clone);
      this.source = null;
    });
  }
}

const drop = new Drop(document.querySelector(".wrap"));
